/**
 * 需要全局变量：$
 * 需要knockout和knockout-validation
 * 需要CryptoJS和enc-base64
 * 需要artDialog
 * 需要perfect-scrollbar.jquery.js
 */
(function (factory) {
    if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        factory(require("knockout"), exports);
    } else if (typeof define === "function" && define["amd"]) {
        define(["knockout", "exports"], factory);
    } else {
        window.hr = window.hr || {};
        factory(ko, hr.common = hr.common || {});
    }
}(function (ko, exports) {
    if (typeof (ko) === 'undefined') {
        throw new Error('Knockout is required, please ensure it is loaded before loading this ko.common plug-in');
    }

    //TODO: 为了兼容
    function logoutRestClient(p) {
        var isBusy = false;
        var tempUrl = "";

        function logoutRestClient(p) {
            return $.ajax({
                type: 'POST',
                contentType: 'application/json;charset=UTF-8',
                url: p.url,
                data: p.data,
                beforeSend: function (xhr) {
                    exports.sessionStorageUtil().clear();
                    ko.dataFor($("body")[0]).currentMenu({menuUrl: ''}); //TODO: 解决bug
                    p.beforeFun && p.beforeFun(xhr);
                },
                complete: function () {
                    isBusy = false;
                    tempUrl = "";
                },
                success: function (data, textStatus, request) {
                    isBusy = false;
                    tempUrl = "";
                    p.successFun && p.successFun(data);
                },
                error: function (xhr, txtStatus, error) {
                    isBusy = false;
                    tempUrl = "";
                    if (4 == xhr.readyState && 403 == xhr.status) {
                        var vm = ko.dataFor($("body")[0]);
                        vm.initPage(mainConfig.loginUrl); //TODO: 需要兼容
                    }
                    p.errorFun && p.errorFun();
                }
            });
        }

        return logoutRestClient(p);
    }

    exports.logoutLoadAjax = function (p) {
        return logoutRestClient(p).success(function (data) {
            p.model = p.model || {};
            if ($.isArray(data.data)) {
                // 处理list数据
                data.data = $.map(data.data, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else if (data && data.data && data.data.content && $.isArray(data.data.content)) {
                // 处理page数据
                data.data.content = $.map(data.data.content, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else {
                if (p.isObservable) {//可观测
                    data = ko.mapping.fromJS($.extend($.extend({}, p.model), data));
                } else {//不可观测
                    data = $.extend($.extend({}, p.model), data);
                }
            }
        });
    };
    // exports.isNotNull = function (value) {
    //     return typeof value != 'undefined' && !!value;
    //
    // };

    window.ko = window.ko || {};
    ko.utils = ko.utils || {};
    ko.utils.checkMenu = function (array, item) {
        var result = false;
        if (array.data) {
            $.each(array.data, function (index, obj) {
                if (obj.menu.id == item.id) {
                    result = true;
                    return false;//终止循环
                } else {
                    result = false;
                }
            });
        }
        return result;
    };

    exports.getCurrentMenuOperations = function (htmlModel, arrayModel) {
        var currentPage = ko.dataFor($("body")[0]).currentMenu();
        var roleId = ko.currentUser.data.currentRoleId;
        var p = {
            url: '/rbacRoleMenu/findAll',
            param: 'search_EQ_role.id=' + roleId + '&search_EQ_menu.id=' + currentPage.id + "&sort_operation.sortNum=ASC"
        };
        exports.loadAjax(p).success(function (data) {
            if (data && data.data && data.data.length > 0) {
                var arrayOperations = [];
                var htmlOperations = [];
                $.each(data.data, function (index, item) {
                    if (item.operation) {
                        if (item.operation.type.id == '12') {
                            if (item.operation.operationContent) {
                                arrayOperations.push(eval('(' + item.operation.operationContent + ')'));
                            }
                        } else if (item.operation.type.id == '11') {
                            if (item.operation.operationContent) {
                                htmlOperations.push(item.operation.operationContent);
                            }
                        }
                    }
                });
                arrayModel(arrayOperations);
                htmlModel(htmlOperations);
            }
        });
    };

    /**
     * 获取拼音首字母
     * @param data 汉字
     */
    exports.translatePy = function (data) {
        var param = {
            url: '/translate/toPy',
            param: 'chinese=' + data
        };
        return exports.loadAjax(param);
    };

    /**
     * 计算机构级别
     * @param data
     */
    exports.calculationLevelNum = function (data) {
        return data * 1 + 1;
    };
    /**
     * 计算下级数据序号
     * @param data 上级序号100000
     * @param type 类型(org,menu)
     */
    exports.calculationSortNum = function (data, type) {
        var url = '';
        var param = '';
        if (type == 'org') {//(以6位为准，每两位为一个级别)
            url = '/rbacOrg/selectSortNum';
            param = 'parentOrgId=' + data;
        }
        if (type == 'menu') {//(以6位为准，每两位为一个级别)
            url = '/rbacMenu/selectSortNum';
            param = 'parentMenuId=' + data;
        }
        if (type == 'role') {//查询最大值
            url = '/rbacRole/selectSortNum';
        }
        if (type == 'operation') {
            url = '/rbacOperation/selectSortNum';
            param = 'menuId=' + data;
        }
        var paramObj = {
            url: url,
            param: param
        };
        return exports.loadAjax(paramObj);
    };

    //TODO: ---------以上是为了兼容------------------------------------

    /**
     * 将yyyy-mm-dd格式时间转换为date格式
     * timeStr: yyyy-mm-dd hh:mm:ss
     */
    exports.fixDate = function (time) {
        if (!document.all) {
            return new Date(time);
        }
        var arr = time.split(time.match(/\D+/g)[2]);
        var date;
        var time;
        if (isNotNull(arr[0])) {
            date = arr[0].split("-");
        }
        if (isNotNull(arr[1])) {
            time = arr[1].split(":");
        }
        return new Date(date[0], date[1] - 1, date[2], time[0], time[1]);
    };

    /**
     * 将日期类型的值转换为 format格式
     * date: 日期型数据
     * format: 转换结果格式
     */
    exports.formatData = function (date, format) {
        var o =
            {
                "M+": date.getMonth() + 1, //month
                "d+": date.getDate(),    //day
                "h+": date.getHours(),   //hour
                "m+": date.getMinutes(), //minute
                "s+": date.getSeconds(), //second
                "q+": Math.floor((date.getMonth() + 3) / 3),  //quarter
                "S": date.getMilliseconds() //millisecond
            };
        if (/(y+)/.test(format))
            format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(format))
                format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
        return format;
    };

    /**
     * 保存之前处理日期
     * 将字符串日期转换为LONG型日期，用于数据库保存
     * dateModel: 可观测的日期
     */
    exports.dealDateBeforeSave = function (dateModel) {
        if (dateModel()) {
            dateModel(exports.fixDate(dateModel()).getTime());
        }
    };

    /**
     * 显示之前处理日期
     * 将LONG型的日期转换为要显示的日期字符串
     */
    exports.dealDateBeforeShow = function (dateModel, format) {
        if (dateModel()) {
            var date = new Date(dateModel());
            dateModel(exports.formatData(date, format));
        }
    };

    /**
     * 返回tableModel
     */
    exports.createTableModel = function (p) {
        var tableModel = {
            url: ko.observable(p.url),
            param: ko.observable(p.param),
            loadData: ko.observable(false),
            tableMainTheadTableColumns: ko.observable(p.columns),
            tablePageItem: ko.observable(p.pageItem),
            operationColumns: ko.observable(p.operation),
            tableTitle: ko.observable(p.title),
            tableData: ko.observableArray(),
            data: ko.observableArray(),
            operationColumnsIsFirst: ko.observable(false)
        };
        return tableModel;
    };

    /**
     * 关闭弹出框
     * obj: 弹出框对象
     */
    exports.closeDialog = function (obj) {
        obj.close().remove();
    };

    /**
     * 弹出加载中提示框
     */
    exports.showLoadingDialog = function (p) {
        var width = "270px";
        var height = "10px";
        if (p.width) {
            width = p.width;
        }
        if (p.height) {
            height = p.height;
        }
        var load = dialog({
            id: 'loading',
            content: '<div class="f-text-center"><i class=\'icon-spin6 animate-spin\'></i><span>' + p.message + '</span></div>',
            width: width,
            height: height
        });
        load.showModal();
        return load;
    };

    /**
     * 弹出消息提示框
     * message, type, timeout
     */
    exports.showAlertDialog = function (p) {
        //TODO: 为了兼容
        if (arguments.length > 1 || typeof p != 'object') {
            var arg1 = p;
            p = {};
            p.message = arg1;
            p.type = arguments[1];
        }

        var content = "";
        if (p.type == 'success') {
            content = '<span class="icon-ok" style=\'font-size: 16px;color: green;padding-right: 10px;\'></span>' + p.message
        } else if (p.type == 'error') {
            content = '<span class="icon-attention" style=\'font-size: 16px;color: red;padding-right: 10px;\'></span>' + p.message
        }
        var title = "消息";
        if (p.title) {
            title = p.title;
        }
        var width = "240px";
        if (p.width) {
            width = p.width;
        }
        var alert = dialog({
            content: content,
            width: width,
            title: title,
            okValue: '确定',
            ok: function () {
                p.okFun && p.okFun();
            },
            cancelValue: '取消',
            cancel: function () {
                p.cancelFun && p.cancelFun();
            },
            drag: false,
            onshow: function () {
                var obj = alert.node;
                var layout = "right-bottom";
                if (p.layout) {
                    layout = p.layout;
                }
                //左下方
                if (layout == "left-bottom") {
                    $(obj)[0].style.left = "0";
                    $(obj)[0].style.top = "";
                    $(obj)[0].style.right = "";
                    $(obj)[0].style.bottom = "0";
                }

                //右下方
                if (layout == "right-bottom") {
                    $(obj)[0].style.left = "";
                    $(obj)[0].style.top = "";
                    $(obj)[0].style.right = "0";
                    $(obj)[0].style.bottom = "0";
                }

                //左上方
                if (layout == "left-top") {
                    $(obj)[0].style.left = "0";
                    $(obj)[0].style.top = "0";
                    $(obj)[0].style.right = "";
                    $(obj)[0].style.bottom = "";
                }

                //右上方
                if (layout == "right-top") {
                    $(obj)[0].style.left = "";
                    $(obj)[0].style.top = "0";
                    $(obj)[0].style.right = "0";
                    $(obj)[0].style.bottom = "";
                }
                var autoClose = true;
                if (p.autoClose) {
                    autoClose = p.autoClose;
                }
                var time = 2000;
                if (p.time) {
                    time = p.time;
                }
                if (autoClose) {
                    setTimeout(function () {
                        alert.close().remove();
                    }, time);
                }
            }
        });
        var showType = "normal";
        if (showType == "normal") {
            alert.show();
        } else if (showType == "modal") {
            alert.showModal();
        }
    };

    /**
     * 弹出选择对话框
     */
    exports.showConfirmDialog = function (p) {
        //TODO: 为了兼容
        if (arguments.length > 1 || typeof p != 'object') {
            var arg1 = p;
            p = {};
            p.message = arg1;
            p.okFun = arguments[1];
        }

        var width = '370px';
        if (p.width) {
            width = p.width;
        }
        var title = '消息';
        if (p.width) {
            title = p.title;
        }
        var confirm = dialog({
            content: '<span class="icon-attention" style=\'font-size: 16px;color: yellow;padding-right: 10px;\'></span>' + p.message,
            width: width,
            title: title,
            okValue: '确定',
            cancelValue: '取消',
            cancel: function () {
                p.cancelFun && p.cancelFun();
            },
            ok: function () {
                p.okFun && p.okFun();
            },
            onshow: function () {
                p.onshow && p.onshow();
            }
        });

        confirm.showModal();
    };

    /**
     * 保存数据成功后关闭弹出框并刷新数据
     * tableModel: tableModel
     * data: ajax返回数据
     * dia: 弹出框
     */
    exports.closeDialogWhenSuccess = function (tableModel, data, dia) {
        if (data && data.status == mainConfig.statusSuccess) {
            exports.showAlertDialog({message: '数据保存成功!', type: 'success'});
            if (tableModel) {
                tableModel.loadData(true);
            }
        } else if (data && data.status == mainConfig.statusError) {
            exports.showAlertDialog({message: '数据保存成功!', type: 'error'});
            return false
        }
        if (dia) {
            exports.closeDialog(dia);
        }
    };

    /**
     * 将source里的值赋值给target里，将source中比target里多出来的值补充到target中
     */
    exports.extend = function (target, source) {
        $.each(source, function (key, val) {
            if (ko.isObservable(target[key])) {
                target[key](val);
            } else {
                target[key] = val;
            }
        });
        return target;
    };

    /**
     * 将data数据中的所有属性转为可观测对象
     * @param data 数据
     * @param items 数据中的object类型的值
     */
    exports.mappingData = function (data, items) {
        var mapping = {};
        if (items && $.isArray(items) && items.length > 0) {
            $.each(items, function (index, item) {
                mapping[item] = {
                    update: function (options) {
                        if (ko.isObservable(options.data)) {
                            return ko.mapping.fromJS(ko.unwrap(options.data), mapping);
                        }
                        return ko.observable(ko.mapping.fromJS(ko.unwrap(options.data), mapping));
                    }
                };
            });
        }
        return ko.mapping.fromJS(data, mapping);
    };

    /**
     * 对sessionStorage的操作
     */
    exports.sessionStorageUtil = function () {
        return {
            setItem: function (key, value) {
                sessionStorage.setItem(key, CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(value))));
            },
            getItem: function (key) {
                if (sessionStorage.getItem(key)) {
                    return $.parseJSON((CryptoJS.enc.Base64.parse(sessionStorage.getItem(key))).toString(CryptoJS.enc.Utf8));
                }
            },
            removeItem: function (key) {
                sessionStorage.removeItem(key);
            },
            clear: function () {
                sessionStorage.clear();
            }
        }
    };

    var isBusy = false;
    var tempUrl = "";

    /**
     * ajax请求数据
     * @param p
     */
    exports.loadAjax = function (p) {
        return exports.restClient(p).success(function (data) {
            if (!p.model) {
                p.model = {};
            }
            if (data) {
                if (data.status == mainConfig.statusSuccess) {//后台返回ResultVo.ok
                    if ($.isArray(data.data)) {
                        data.data = $.map(data.data, function (item) {
                            if (p.isObservable) {//可观测
                                return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                            } else {//不可观测
                                return $.extend($.extend({}, p.model), item);
                            }
                        });
                    } else {
                        if (data.data && data.data.content && $.isArray(data.data.content)) {
                            data.data.content = $.map(data.data.content, function (item) {
                                if (p.isObservable) {//可观测
                                    return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                                } else {//不可观测
                                    return $.extend($.extend({}, p.model), item);
                                }
                            });
                        } else {
                            if (p.isObservable) {//可观测
                                data = ko.mapping.fromJS($.extend($.extend({}, p.model), data));
                            } else {//不可观测
                                data = $.extend($.extend({}, p.model), data);
                            }
                        }
                    }
                } else if (data.status == '0') {    //TODO: 需要扩展的地方
                    exports.showAlertDialog(data.message, 'error');
                }
            }

        });
    };

    /**
     * restClient
     */
    exports.restClient = function (p) {
        var async = "POST";
        if (p.async) {
            async = p.async;
        }
        if (isBusy && tempUrl == p.url) return;
        var url = p.url;
        tempUrl = p.url;
        if (p.param && p.param != null && p.param != "") {
            url = url + "?" + p.param;
        }
        var data = null;
        if (p.jsonParam && p.jsonParam != null && p.jsonParam != "") {
            data = p.jsonParam;
        }
        isBusy = true;
        return $.ajax({
            type: async,
            contentType: 'application/json;charset=UTF-8',
            url: url,
            data: data || '{}',
            beforeSend: function (xhr) {
                if (exports.sessionStorageUtil().getItem("X-AUTH-TOKEN")) {
                    xhr.setRequestHeader('X-AUTH-TOKEN', exports.sessionStorageUtil().getItem("X-AUTH-TOKEN").token);
                }
                p.beforeFun && p.beforeFun(xhr);
            },
            complete: function () {
                isBusy = false;
            },
            success: function (data, textStatus, request) {
                isBusy = false;
                if (request.getResponseHeader("X-AUTH-TOKEN")) {
                    exports.sessionStorageUtil().setItem("X-AUTH-TOKEN", {token: request.getResponseHeader("X-AUTH-TOKEN")});
                }
                p.successFun && p.successFun(data);
            },
            error: function (xhr, txtStatus, error) {
                isBusy = false;
                if (4 == xhr.readyState && 403 == xhr.status) {
                    var vm = ko.dataFor($("body")[0]);
                    vm.indexPage(mainConfig.loginUrl);
                }
                if (1001 == xhr.status) {
                    exports.showAlertDialog('用户名输入错误!', 'error');
                    return;
                }
                if (1002 == xhr.status) {
                    exports.showAlertDialog('密码输入错误!', 'error');
                    return;
                }
                if (p.errorFun) {
                    p.errorFun();
                } else {
                    goErrorPage(500000);
                }
            }
        });
    };

    /**
     * 跳转错误页面
     */
    function goErrorPage(code, message) {
        // app.log(code);
        // app.log(message);
    }

    /**
     * 判断字段不为空
     * @param value
     * @returns {boolean}
     */
    function isNotNull(value) {
        if (value && value != null && value != "" && value.length != 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 弹出有遮罩的页面
     * @param obj
     * @param viewModel
     */
    exports.showModalDialog = function (obj, viewModel) {
        //TODO: 为了兼容
        if (obj.url) {
            obj.uurl = obj.url;
        }

        if (obj.uurl) {
            $.get(obj.uurl, null, function (response, status, xhr) {
                obj.content(response);
                obj.showModal();
                if (viewModel) {
                    ko.applyBindings(viewModel, $("#content\\:" + obj.id)[0]);
                }
                if (obj.options.height) {
                    $("#content\\:" + obj.id).perfectScrollbar();
                }
            });
        }
    };

    /**
     * 弹出无遮罩弹出框
     * @param obj
     */
    exports.showDialog = function (obj, viewModel) {
        //TODO: 为了兼容
        if (obj.url) {
            obj.uurl = obj.url;
        }

        if (obj.uurl) {
            $.get(obj.uurl, null, function (response, status, xhr) {
                obj.content(response);
                obj.show();
                if (viewModel) {
                    ko.applyBindings(viewModel, $("#content\\:" + obj.id)[0]);
                }
                if (obj.options.height) {
                    $("#content\\:" + obj.id).perfectScrollbar();
                }
            });
        }
    };

    /**
     * 将汉字转为拼音
     */
    exports.transformationToPy = function (value) {
        var p = {
            url: '/transformation/toPy',
            param: 'chinese=' + value
        };
        return exports.loadAjax(p);
    };


    /**
     * knockout验证字段
     */
    exports.isErrors = function (viewModel) {
        if (ko.validation.group(viewModel)().length > 0) {
            ko.validation.group(viewModel).showAllMessages();
            return false;
        } else {
            return true;
        }
    };

    /**
     * 获取时间段
     * type: day-今日， week-本周， month-月， year-年
     */
    exports.getTimePart = function (type) {
        var timePart = "";
        var date = new Date();
        var timeStart = "";
        var timeEnd = "";
        var hourStart = "00:00:01";
        var hourEnd = "23:59:59";
        var nowDay = date.getDay();//当前是一周的第几天
        var daySeconds = 1 * 24 * 60 * 60 * 1000;//一天的毫秒数
        var currentDate = formatData(date, "yyyy-MM-dd");//当前日期
        var currentYearAndMonth = formatData(date, "yyyy-MM");//当前年月
        if (type == "day") {
            timeStart = +new Date(currentDate + " " + hourStart);
            timeEnd = +new Date(currentDate + " " + hourEnd);
        } else if (type == "week") {
            timeStart = +new Date(currentDate + " " + hourStart) - (nowDay - 1) * 1 * daySeconds;
            timeEnd = +new Date(currentDate + " " + hourEnd) + (7 - nowDay) * 1 * daySeconds;
        } else if (type == "month") {
            timeStart = +new Date(currentYearAndMonth + "-01 " + hourStart);
            timeEnd = +new Date(formatData(new Date(date.getFullYear(), date.getMonth() + 1, 0), "yyyy-MM-dd") + " " + hourEnd);
        } else if (type == "year") {
            timeStart = +new Date(date.getFullYear() + "-01-01 " + hourStart);
            timeEnd = +new Date(date.getFullYear() + "-12-31 " + hourEnd);
        }
        timePart = timeStart + "-" + timeEnd;
        return timePart;
    };

    /**
     * 根据key获取url中的参数
     *
     * @param key 参数key
     * @param url 为空时表示window.location
     * @returns {null}
     */
    exports.getUrlParam = function (key, url) {
        var searchUrl = '';
        if (url) {
            searchUrl = url.split('?')[1];
        } else {
            searchUrl = window.location.search.substr(1);
        }
        if (!searchUrl) {
            return null;
        }
        var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
        var r = searchUrl.match(reg);
        if (r && $.isArray(r) && r[2]) return unescape(r[2]);
        return null;
    };

    /**
     * 根据key获取cookie中的参数值
     *
     * @param key 参数key
     * @returns {null}
     */
    exports.getCookie = function (key) {
        var arr, reg = new RegExp("(^| )" + key + "=([^;]*)(;|$)");
        if (arr = document.cookie.match(reg)) {
            return unescape(arr[2]);
        } else {
            return null;
        }
    };

    exports.isNotNull = function (val) {
        return typeof val != 'undefined' && val;
    }
}));